package zybNet

import (
	"bytes"
	"zyb/zybPublic"
)

/************协议格式************************************

header(4) | packetlen(4) | funcode(4) | sid(4) | data(?)        | end(4)
0:4       | 4:8          | 8:12       | 12:16  | 16:packetlen-4 | packetlen-4:packetlen
*******************************************************/

type PackStaus uint32

const (
	packetstaus_success uint32 = 1
	packetstaus_error   uint32 = 2
	packetstaus_pending uint32 = 0
)

func (v PackStaus) isSuccess() bool {
	return v == packetstaus_success
}

func (v PackStaus) isError() bool {
	return v == packetstaus_error
}

func (v PackStaus) isPending() bool {
	return v == packetstaus_pending
}

type Header uint32

func (v Header) isHeader() bool {
	return v == 0xFF
}

type Tail uint32

func (v Tail) isTail() bool {
	return v == 0x00
}

const (
	HEADERFlag   uint32 = 0xFF
	ENDFlag      uint32 = 0x00
	EmptyPackLen uint32 = 4 + 8 + 4
)

type Packet struct {
	fcode int
	sid   int
	msg   []byte
}

func (p *Packet) EnPack(fcode, sid int, msg []byte) []byte {
	p.fcode = fcode
	p.sid = sid
	p.msg = append(p.msg, msg)
	nLen := EmptyPackLen + len(msg)

	buf := append(zybPublic.IntToBytes(HEADERFlag), zybPublic.IntToBytes(nLen),
		zybPublic.IntToBytes(fcode), zybPublic.IntToBytes(sid),
		msg, zybPublic.IntToBytes(ENDFlag)...)

	return buf
}

func (p *Packet) UnPack(buf []byte) ([]byte, PackStaus) {
	if len(buf) < 4 {
		return buf, packetstaus_pending
	}

	// 检查包头
	h := zybPublic.BytesToInt(buf[0:4])
	if Header(h).isHeader() == false {
		return buf, packetstaus_error
	}

	nLen := zybPublic.BytesToInt(buf[4:8])

	if len(buf) < nLen {
		return buf, packetstaus_pending
	}

	// 检查包尾
	t := zybPublic.BytesToInt(buf[nLen-4 : nLen])
	if Tail(t).isTail() == false {
		return buf, packetstaus_error
	}

	p.fcode = zybPublic.BytesToInt(buf[8:12])
	p.sid = zybPublic.BytesToInt(buf[12:16])
	p.msg = buf[16 : nLen-4]

	if nLen == len(buf) {
		buf = make([]byte, 0)
	}

	return buf, packetstaus_success
}
